﻿using System;
using System.Windows;

namespace Microsoft.Popfly.GameCreator.GameEngine.Behaviors
{
    public abstract class RotateTowardBehavior : RotateBehavior
    {
        protected Actor m_actorOwner;
        protected Game m_game;
        protected double m_offsetFromFacing;
        public RotateTowardBehavior(Game game, BehaviorOwner owner, double offset, double offsetFromFacingInRadians)
            : base(owner, offset)
        {
            if (owner.IsActor == false)
            {
                throw new ArgumentException("Rotation behaviors are only implemented for actors");
            }

            m_actorOwner = (Actor)owner;
            m_game = game;
            m_offsetFromFacing = offsetFromFacingInRadians;
        }
    }

    #region TowardRadians
    public class AccelerationRotateTowardRadians : RotateTowardBehavior
    {
        public AccelerationRotateTowardRadians(Game game, BehaviorOwner owner, double acceleration, double offsetFromTopInRadians)
            : base(game, owner, acceleration, offsetFromTopInRadians) {}

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardRadiansAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_offset, m_offsetFromFacing);
        }
    }

    public class MaxSpeedRotateTowardRadians : RotateTowardBehavior
    {
        public MaxSpeedRotateTowardRadians(Game game, BehaviorOwner owner, double maxSpeed, double offsetFromTopInRadians)
            : base(game, owner, maxSpeed, offsetFromTopInRadians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardRadiansMaxSpeed(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_offset, m_actorOwner.RotationDrag, m_offsetFromFacing);
        }
    }

    public class VelocityRotateTowardRadians : RotateTowardBehavior
    {
        public VelocityRotateTowardRadians(Game game, BehaviorOwner owner, double velocity, double offsetFromTopInRadians)
            : base(game, owner, velocity, offsetFromTopInRadians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationVelocity += MoveHelpers.RotateTowardRadiansAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_offset, m_offsetFromFacing);
        }
    }
    #endregion 

    #region TowardPoint
    public class AccelerationRotateTowardPoint : RotateTowardBehavior
    {
        private Point m_rotateToward;
        public AccelerationRotateTowardPoint(Game game, BehaviorOwner owner, Point rotateToward, double acceleration, double offsetFromFacingInRadians)
            : base(game, owner, acceleration, offsetFromFacingInRadians)
        {
            m_rotateToward = rotateToward;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_rotateToward, m_offset, m_offsetFromFacing);
        }
    }

    public class MaxSpeedRotateTowardPoint : RotateTowardBehavior
    {
        private Point m_rotateToward;
        public MaxSpeedRotateTowardPoint(Game game, BehaviorOwner owner, Point rotateToward, double maxSpeed, double offsetFromFacingInRadians)
            : base(game, owner, maxSpeed, offsetFromFacingInRadians)
        {
            m_rotateToward = rotateToward;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardMaxSpeed(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_rotateToward, m_offset, m_actorOwner.RotationDrag, m_offsetFromFacing);
        }
    }

    public class VelocityRotateTowardPoint : RotateTowardBehavior
    {
        private Point m_rotateToward;
        public VelocityRotateTowardPoint(Game game, BehaviorOwner owner, Point rotateToward, double velocity, double offsetFromFacingInRadians)
            : base(game, owner, velocity, offsetFromFacingInRadians)
        {
            m_rotateToward = rotateToward;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationVelocity += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_rotateToward, m_offset, m_offsetFromFacing);
        }
    }
    #endregion 

    #region TowardMouse
    public class AccelerationRotateTowardMouse : RotateTowardBehavior
    {
        public AccelerationRotateTowardMouse(Game game, BehaviorOwner owner, double acceleration, double offsetFromFacingInRadians)
            : base(game, owner, acceleration, offsetFromFacingInRadians) { }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_game.MousePosition, m_offset, m_offsetFromFacing);
        }
    }

    public class MaxSpeedRotateTowardMouse : RotateTowardBehavior
    {
        public MaxSpeedRotateTowardMouse(Game game, BehaviorOwner owner, double maxSpeed, double offsetFromFacingInRadians)
            : base(game, owner, maxSpeed, offsetFromFacingInRadians) { }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardMaxSpeed(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_game.MousePosition, m_offset, m_actorOwner.RotationDrag, m_offsetFromFacing);
        }
    }

    public class VelocityRotateTowardMouse : RotateTowardBehavior
    {
        public VelocityRotateTowardMouse(Game game, BehaviorOwner owner, double velocity, double offsetFromFacingInRadians)
            : base(game, owner, velocity, offsetFromFacingInRadians) { }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_actorOwner.RotationVelocity += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_game.MousePosition, m_offset, m_offsetFromFacing);
        }
    }
    #endregion 

    #region TowardActor
    public class AccelerationRotateTowardActor : RotateTowardBehavior
    {
        private string m_actorName;
        public AccelerationRotateTowardActor(Game game, BehaviorOwner owner, string actorName, double acceleration, double offsetFromFacingInRadians)
            : base(game, owner, acceleration, offsetFromFacingInRadians)
        {
            m_actorName = actorName;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor actor = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_actorOwner.GetCenterX(), m_actorOwner.GetCenterY());
			if (actor != null)
			{
				m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), actor.GetObjectCenter(), m_offset, m_offsetFromFacing);
			}
        }
    }

    public class MaxSpeedRotateTowardActor : RotateTowardBehavior
    {
        private string m_actorName;
        public MaxSpeedRotateTowardActor(Game game, BehaviorOwner owner, string actorName, double maxSpeed, double offsetFromFacingInRadians)
            : base(game, owner, maxSpeed, offsetFromFacingInRadians)
        {
            m_actorName = actorName;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor actor = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_actorOwner.GetCenterX(), m_actorOwner.GetCenterY());
			if (actor != null)
			{
				m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardMaxSpeed(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), actor.GetObjectCenter(), m_offset, m_actorOwner.RotationDrag, m_offsetFromFacing);
			}
        }
    }

    public class VelocityRotateTowardActor : RotateTowardBehavior
    {
        private string m_actorName;
        public VelocityRotateTowardActor(Game game, BehaviorOwner owner, string actorName, double velocity, double offsetFromFacingInRadians)
            : base(game, owner, velocity, offsetFromFacingInRadians)
        {
            m_actorName = actorName;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor actor = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_actorOwner.GetCenterX(), m_actorOwner.GetCenterY());
			if (actor != null)
			{
				m_actorOwner.RotationVelocity += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), actor.GetObjectCenter(), m_offset, m_offsetFromFacing);
			}
        }
    }
    #endregion 

    #region TowardActorInstance
    public class AccelerationRotateTowardActorInstance : RotateTowardBehavior
    {
        private Actor m_actor;
        public AccelerationRotateTowardActorInstance(Game game, BehaviorOwner owner, Actor actor, double acceleration, double offsetFromFacingInRadians)
            : base(game, owner, acceleration, offsetFromFacingInRadians)
        {
            m_actor = actor;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            if (!m_actor.Removed)
            {
                m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_actor.GetObjectCenter(), m_offset, m_offsetFromFacing);
            }
        }
    }

    public class MaxSpeedRotateTowardActorInstance : RotateTowardBehavior
    {
        private Actor m_actor;
        public MaxSpeedRotateTowardActorInstance(Game game, BehaviorOwner owner, Actor actor, double maxSpeed, double offsetFromFacingInRadians)
            : base(game, owner, maxSpeed, offsetFromFacingInRadians)
        {
            m_actor = actor;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            if (!m_actor.Removed)
            {
                m_actorOwner.RotationAcceleration += MoveHelpers.RotateTowardMaxSpeed(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_actor.GetObjectCenter(), m_offset, m_actorOwner.RotationDrag, m_offsetFromFacing);
            }
        }
    }

    public class VelocityRotateTowardActorInstance : RotateTowardBehavior
    {
        private Actor m_actor;
        public VelocityRotateTowardActorInstance(Game game, BehaviorOwner owner, Actor actor, double velocity, double offsetFromFacingInRadians)
            : base(game, owner, velocity, offsetFromFacingInRadians)
        {
            m_actor = actor;
        }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            if (!m_actor.Removed)
            {
                m_actorOwner.RotationVelocity += MoveHelpers.RotateTowardAorV(m_game.DeltaTimeInSeconds, m_actorOwner.Rotation, m_actorOwner.GetObjectCenter(), m_actor.GetObjectCenter(), m_offset, m_offsetFromFacing);
            }
        }
    }
    #endregion 
}
